/*****************************************************************************/
/*                        >>> func_ipc.c <<<                                 */
/*	Trabajo Practico 2do. cuatrimestre 2011                                  */
/*	TP:"FUSELAJE"                                                            */
/*	GRUPO: Reduce Fat Fast                                                   */
/*	INTEGRANTES: Emanuel Genovese                                            */
/*               Federico Gabriel Garcia                                     */
/*               Federico Pioli                                              */
/*               Esther Insfrain                                             */
/*               Luciano Bagattin                                            */
/*	Fecha UM:                                                                */
/*****************************************************************************/

/*****************************************************************************/
/*		        	Include					                                 */
/*****************************************************************************/

#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <unistd.h>
#include <netinet/in.h>
#include "structs_commons.h"
#include "constants_commons.h"
#include "log.h"
#include "func_strings.h"

/*#include "estructuras.h"
 #include "prototipos.h"
 #include "func_log.h"
 #include "constantes.h"*/

/******************************************************************************/
/* Nombre de Procedimiento: fGenerar_Desc_ID                                   */
/* Parametros: no recibe parametros                                           */
/*                                                                            */
/*	                                                                          */
/* Descripcion: Funcion que se encarga de preparar el socket tanto para       */
/*              cuando es cliente o cuando es servidor.                       */
/******************************************************************************/

char* fGenerar_Desc_ID(void) {
	static char ID[16] = "\0";
	unsigned int i;
	time_t tiempo;

	tiempo = time(NULL);
	srand(tiempo);
	for (i = 0; i < 16; i++) {
		if ((rand() % 2) == 0) {
			ID[i] = 97 + rand() % 25;
		} else {
			ID[i] = 48 + rand() % 10;
		}
	}
	return ID;
}

/******************************************************************************/
/* Nombre de Procedimiento: fMandarIPCXsocket                                 */
/* Parametros: iSocket: socket para envio de mensajes                         */
/*             st:estructura de envio de IPC                                  */
/*             log: archivo de logueo                                         */
/* Descripcion: Funcion que se encarga de preparar el socket tanto para       */
/*              cuando es cliente o cuando es servidor.                       */
/******************************************************************************/
int fMandarIPCXsocket(int iSocket, stNIPC st, t_log *log) {

	//manda head
	int iOperados = -11;
	int fEnvio_OK = 0;
	//char * cadenaEnvio;
	//int iTamanio;

	//fin del switch

	if (strcmp(st.sDescriptorOriginal, "NULL") == 0) {
		//memcpy(cadenaEnvio,(char*) fGenerar_Desc_ID ( ) , 16);
	} else {
		//memcpy(cadenaEnvio, st.sDescriptorOriginal , 16);
	}
	//memcpy(cadenaEnvio+16, &st.iPayloadDescriptor, sizeof(int));
	//memcpy(cadenaEnvio+20, &st.sPayload_lenth, sizeof(short int));
	switch (st.iPayloadDescriptor) {
	case 1:

		break;
	}
	if (iSocket != -1) {
		while (fEnvio_OK == 0) {
			/*if ( ( iOperados = send ( iSocket , cadenaEnvio , iTamanio , 0 ) ) == -1 ) devuelve datos{



			 fEnvio_OK = 2;
			 }*/
			//	if ( iTamanio == iOperados ) fEnvio_OK = 1;
			if (iOperados == 0)
				fEnvio_OK = 2;
		}
		//fGrabarLog(3, "Exito al mandar el HeaderNIPCS", iTipo);

		if (fEnvio_OK == 2)
			iOperados = -1;
	} //fin del if

	return (iOperados == -1) ? 0 : iOperados;
}

/******************************************************************************/
/* Nombre de Procedimiento: ffRecibirIPCXsocket                               */
/* Parametros: iSocket: socket de recepcion de mensajes                       */
/*             stMSect: estructura de donde guarda el envio de mensajes       */
/*   	       log: archivo de log                                            */
/* Descripcion: Funcion que se encarga de preparar el socket tanto para       */
/*              cuando es cliente o cuando es servidor.                       */
/******************************************************************************/

int fRecibirIPCXsocket(int iSocket, stNIPC * stMSect, t_log *log) {
	int iOperados = -10;
	//int fEnvio_OK = 0;

	//char *cadenaRecepcion;

	//int tamanio=0;
	int iMaxBuffer = 0;
	int iFlag = 1;

	//cadenaRecepcion=HeapAlloc(hHeap, 0, (sizeof(char)*16)+sizeof(int)+sizeof(long int));
	iMaxBuffer = (sizeof(char) * 16) + sizeof(int) + sizeof(long int);
	if (iSocket != -1) {
		/*  while(( iOperados = recv ( iSocket, cadenaRecepcion ,iMaxBuffer, MSG_PEEK)) ==iMaxBuffer){
		 iMaxBuffer +=512;


		 }*/ //fin del while
		// iOperados = recv(iSocket, cadenaRecepcion ,iMaxBuffer,0);
		if ((iOperados == -1) || (iOperados == 0)) {
			//  fGrabarLog(1, "Error al enviar el Body IPC", iTipo);
			iFlag = 0;
			iOperados = -1;
		}

	} //fin del if
	if (iFlag) {
		switch (iOperados) {
		case 1:
			break;
		}
	}

	return (iOperados == -1) ? 0 : iOperados;
} //fin del fRecibirIPCXsocket

/******************************************************************************/
/* Nombre de Procedimiento: fcmpDescriptor                                    */
/* Parametros: no recibe parametros                                           */
/*                                                                            */
/*	                                                                          */
/* Descripcion: Funcion que se encarga de preparar el socket tanto para       */
/*              cuando es cliente o cuando es servidor.                       */
/******************************************************************************/

int fcmpDescriptor(char* ID1, char* ID2) {
	int i, status = 0;

	for (i = 0; i < 16; i++) {
		if (ID1[i] != ID2[i])
			status = 1;
	}
	return status;
}

/******************************************************************************/
/* Nombre de Procedimiento: stPEscrituraSector_serializer                     */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/
t_stream * stPEscrituraSector_serializer(void *sT) {
	stPEscrituraSector *st = (stPEscrituraSector *) sT;

	t_stream * p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0;
	p->data = malloc(sizeof(stPEscrituraSector));
	memcpy(p->data, st, tmp_size = sizeof(stPEscrituraSector));

	p->length = tmp_size;

	return p;
}

/******************************************************************************/
/* Nombre de Procedimiento: stPEscrituraSector_serializer                     */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/

void stPEscrituraSector_deserializer(t_stream * p, stPEscrituraSector **m) {

	int tmp_size = 0;
	*m = (stPEscrituraSector *) malloc(sizeof(stPEscrituraSector));
	memcpy(*m, p->data, tmp_size = sizeof(stPEscrituraSector));

} //fin del stPEscrituraSector_deserializer

/******************************************************************************/
/* Nombre de Procedimiento: stPEscrituraSector_serializer                     */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/
t_stream * stPosCabezal_serializer(void *sT) {
	vecTrace *st = (vecTrace *) sT;

	t_stream * p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0;
	p->data = malloc(sizeof(vecTrace));
	memcpy(p->data, st, tmp_size = sizeof(vecTrace));

	p->length = tmp_size;

	return p;
}

/******************************************************************************/
/* Nombre de Procedimiento: stPosCabezal_deserializer                         */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/

void stPosCabezal_deserializer(t_stream * p, vecTrace **m) {

	int tmp_size = 0;
	*m = (vecTrace *) malloc(sizeof(vecTrace));
	memcpy(*m, p->data, tmp_size = sizeof(vecTrace));

} //fin del stPEscrituraSector_deserializer

/******************************************************************************/
/* Nombre de Procedimiento: stREscrituraSector_serializer                     */
/* Parametros: st:estructura de respuesta escritura sector a serializar       */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/
t_stream * stREscrituraSector_serializer(void *sT) {
	stREscrituraSector *st = (stREscrituraSector *) sT;

	t_stream * p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0;
	p->data = malloc(sizeof(stREscrituraSector));
	memcpy(p->data, st, tmp_size = sizeof(stREscrituraSector));

	p->length = tmp_size;

	return p;

} //fin del stREscrituraSector_serializer

/******************************************************************************/
/* Nombre de Procedimiento: stREscrituraSector_serializer                     */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stREscrituraSector    */
/******************************************************************************/

void stREscrituraSector_deserializer(t_stream * p, stREscrituraSector **m) {

	int tmp_size = 0;
	*m = (stREscrituraSector *) malloc(sizeof(stREscrituraSector));
	memcpy(*m, p->data, tmp_size = sizeof(stREscrituraSector));

} //fin del stREscrituraSector_deserializer

/******************************************************************************/
/* Nombre de Procedimiento: stREscrituraSector_serializer                     */
/* Parametros: st:estructura de respuesta escritura sector a serializar       */
/* Descripcion: Funcion que se serializa una estructura stPEscrituraSector    */
/******************************************************************************/
t_stream * stRLecturaSector_serializer(void *sT) {
	stRLecturaSector *st = (stRLecturaSector *) sT;

	t_stream * p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0;
	p->data = malloc(sizeof(stRLecturaSector));
	memcpy(p->data, st, tmp_size = sizeof(stRLecturaSector));

	p->length = tmp_size;

	return p;

} //fin del stREscrituraSector_serializer

/******************************************************************************/
/* Nombre de Procedimiento: stREscrituraSector_serializer                     */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stREscrituraSector    */
/******************************************************************************/

void stRLecturaSector_deserializer(t_stream * p, stRLecturaSector **m) {

	int tmp_size = 0;
	*m = (stRLecturaSector *) malloc(sizeof(stRLecturaSector));
	memcpy(*m, p->data, tmp_size = sizeof(stRLecturaSector));

} //fin del stREscrituraSector_deserializer

/******************************************************************************/
/* Nombre de Procedimiento: stPLecturaSector_serializer                       */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stPLecturaSector      */
/******************************************************************************/
t_stream * stPLecturaSector_serializer(void *pedido) {
	int *iSector = (int*) pedido;

	t_stream*p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0;

	p->data = malloc(sizeof(int));
	memcpy(p->data, iSector, tmp_size = sizeof(int));
	p->length = tmp_size;
	return p;
}

/******************************************************************************/
/* Nombre de Procedimiento: stPLecturaSector_deserializer                     */
/* Parametros: tOrigen:posicion del cabezal o sector a leer                   */
/* Descripcion: Funcion que se deserializa una estructura stream a            */
/*              stPLecturaSector                                              */
/******************************************************************************/
void stPLecturaSector_deserializer(t_stream * tOrigen, int ** iPunResultado) {
	char sCadena[1024] = "\0";

	*iPunResultado = malloc(sizeof(int));
	memcpy(*iPunResultado, tOrigen->data, tOrigen->length);

} //fin stPLecturaSector

/******************************************************************************/
/* Nombre de Procedimiento: stTracer_serializer                               */
/* Parametros: st:estructura de escritura sector a serializar                 */
/* Descripcion: Funcion que se serializa una estructura stTrace               */
/******************************************************************************/

t_stream * stTrace_serializer(void *sT) {
	stTrace *st = (stTrace *) sT;

	t_stream * p = (t_stream *) malloc(sizeof(t_stream));
	int tmp_size = 0, offset = 0;
	p->data = malloc(sizeof(stTrace));
	memcpy(p->data, st, tmp_size = sizeof(stTrace));

	p->length = tmp_size;
	return p;
}

/******************************************************************************/
/* Nombre de Procedimiento: stTracer_deserializer                             */
/* Parametros: st:estructura de tracer a serializar                           */
/* Descripcion: Funcion que se deserializa a una estructura stTrace           */
/******************************************************************************/

void stTrace_deserializer(t_stream * q, stTrace ** sT) {

	int offset = 0, tmp_size = 0;
	*sT = (stTrace*) malloc(sizeof(stTrace));
	memcpy(*sT, q->data, tmp_size = sizeof(stTrace));

} /******************************************************************************/
/* Nombre de Funcion: stNIPC_serializer                                       */
/* Parametros: st:estructura que se va a serializar                           */
/*             h: puntero a void que es loq ue se va a mandar en el payload   */
/* Descripcion: Funcion que serializa una estructura stNIPC                   */
/******************************************************************************/

t_stream * stNIPC_serializer(stNIPC *St, void * a,
		t_stream *(*serializer)(void*)) {
	t_stream *p = (t_stream *) malloc(sizeof(t_stream));
	char *data;
	t_stream *q = NULL;

	int offset = 0, tmp_size = 0;

	if (a != NULL) {

		q = serializer(a);

		data = (char*) malloc(sizeof(stNIPC) + q->length);
		memcpy(data, &St->iPayloadDescriptor, tmp_size = sizeof(int));
		offset += tmp_size;

		memcpy(data + offset, &St->sDescriptorOriginal,
				tmp_size = sizeof(char) * 16);
		offset += tmp_size;
		memcpy(data + offset, &St->iType, tmp_size = sizeof(int));
		offset += tmp_size;
		memcpy(data + offset, &St->sPayload_lenth, tmp_size =
				sizeof(short int));
		offset += tmp_size;
		memcpy(data + offset, q->data, q->length);

		offset += q->length;

		p->data = data;
		p->length = offset;

	} else {

		data = (char *) malloc(sizeof(stNIPC));

		memcpy(data, &St->iPayloadDescriptor, tmp_size = sizeof(int));
		offset += tmp_size;
		memcpy(data + offset, &St->sDescriptorOriginal,
				tmp_size = sizeof(char) * 16);
		offset += tmp_size;
		memcpy(data + offset, &St->iType, tmp_size = sizeof(int));
		offset += tmp_size;
		memcpy(data + offset, &St->sPayload_lenth, tmp_size =
				sizeof(short int));
		offset += tmp_size;
		p->data = data;
		p->length = offset;

	} //fin del if

	return p;
} //fin del stNIPC_serializer

/******************************************************************************/
/* Nombre de Funcion: stNIPC_deserializer                                       */
/* Parametros: st:estructura que se va a serializar                           */
/*             h: puntero a void que es loq ue se va a mandar en el payload   */
/* Descripcion: Funcion que serializa una estructura stNIPC                   */
/******************************************************************************/

void stNIPC_deserializer(t_stream *st, stNIPC *stIPC) {

	int offset = 0, tmp_size = 0;

	memcpy(&(stIPC->iPayloadDescriptor), st->data, tmp_size = sizeof(int));
	offset = tmp_size;
	memcpy(&(stIPC->sDescriptorOriginal), (st->data) + offset, tmp_size = 16);
	offset += tmp_size;
	memcpy(&(stIPC->iType), (st->data) + offset, tmp_size = sizeof( int));
	offset += tmp_size;
	memcpy(&(stIPC->sPayload_lenth), (st->data) + offset, tmp_size =
			sizeof(unsigned short int));
	offset += tmp_size;

}
